﻿using System;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Windows.Resources;
using Mido.Domain;
using Mido.UiModules.SettingsModule;
using Mido.Utils.Watermark;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Mido.Controls
{
    public class WatermarkedImage : Image
    {
        public static readonly DependencyProperty ImageProperty =
            DependencyProperty.Register("Image", typeof (ProcessedImage), typeof (WatermarkedImage), new PropertyMetadata(null, OnImageChanged));
        
        public static readonly DependencyProperty SettingsProperty =
            DependencyProperty.Register("Settings", typeof (SettingsModel), typeof (WatermarkedImage), new PropertyMetadata(null, OnSettingsChanged));

        private Point? _diff;
        private Rect _bounds;

        private readonly DrawingGroup _drawingVisual = new DrawingGroup();

        public SettingsModel Settings
        {
            get { return (SettingsModel) GetValue(SettingsProperty); }
            set { SetValue(SettingsProperty, value); }
        }

        public ProcessedImage Image
        {
            get { return (ProcessedImage) GetValue(ImageProperty); }
            set { SetValue(ImageProperty, value); }
        }

        private static void OnImageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            WatermarkedImage target = (WatermarkedImage)d;
            target.OnImageChanged((ProcessedImage)e.OldValue, (ProcessedImage)e.NewValue);
        }

        private static void OnSettingsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            WatermarkedImage target = (WatermarkedImage)d;
            target.OnSettingsChanged((SettingsModel)e.OldValue, (SettingsModel)e.NewValue);
        }
        
        private void OnSettingsChanged(SettingsModel oldValue, SettingsModel newValue)
        {
            if (oldValue != null)
                oldValue.Changed -= RefreshPicture;
            if (newValue != null)
                newValue.Changed += RefreshPicture;
        }
		
	    public WatermarkedImage()
        {
            Source = new DrawingImage(_drawingVisual);
        }

        private void OnImageChanged(ProcessedImage oldValue, ProcessedImage newValue)
        {
            if (oldValue != null)
            {
	            oldValue.CustomPositionChanged -= RefreshPicture;
	            oldValue.RotateAngleChanged -= RefreshPicture;
            }

            if (newValue != null)
            {
	            newValue.CustomPositionChanged += RefreshPicture;
				newValue.RotateAngleChanged += RefreshPicture;
            }

            RefreshPicture();
        }

        private void RefreshPicture()
        {
            if (Image == null)
            {
                _drawingVisual.Open().Close();
                return;
            }
            
            DrawingContext context = _drawingVisual.Open();
            context.DrawImage(Image.FullImage, new Rect(0, 0, Image.FullImage.PixelWidth, Image.FullImage.PixelHeight));
            _bounds = WatermarkHelper.OnRender(Image, context);
            context.Close();
        }

        private Point GetMousePosition(MouseEventArgs e)
        {
            Point mousePosition = e.GetPosition(this);
            double scale = ActualWidth / Image.FullImage.PixelWidth;
            
            return new Point(mousePosition.X / scale, mousePosition.Y / scale);
        }
        
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            Point mousePosition = GetMousePosition(e); 
            
            if (Source != null && _bounds.Contains(mousePosition))
            {
                _diff = new Point(mousePosition.X - _bounds.X, mousePosition.Y - _bounds.Y);
                CaptureMouse();

				Uri uri = new Uri("Mido;component/Styles/CursorHand.cur", UriKind.RelativeOrAbsolute);
				StreamResourceInfo info = Application.GetResourceStream(uri);

				Cursor = new Cursor(info.Stream);
            }

            base.OnMouseLeftButtonDown(e);
        }

        protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
        {
            if (_diff.HasValue)
            {
                _diff = null;
                ReleaseMouseCapture();
                Cursor = Cursors.Arrow;
            }

            base.OnMouseLeftButtonUp(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            Point mousePosition = GetMousePosition(e);            
            if (_diff.HasValue)
            {
                double x = mousePosition.X - _diff.Value.X;

                if (x < 5)
                    x = 5;
                if (x > Image.FullImage.PixelWidth - _bounds.Width -5)
                    x = Image.FullImage.PixelWidth - _bounds.Width - 5;

                double y = mousePosition.Y - _diff.Value.Y;

                if (y < 5)
                    y = 5;
                if (y > Image.FullImage.PixelHeight - _bounds.Height - 5)
                    y = Image.FullImage.PixelHeight - _bounds.Height - 5;

				if (Image.Settings.WatermarkAngle == WatermarkAngle.a0)
					Image.CustomPosition = new Point(x, y);
				else if (Image.Settings.WatermarkAngle == WatermarkAngle.a90)
					Image.CustomPosition = new Point(x + _bounds.Width, y);
				else if (Image.Settings.WatermarkAngle == WatermarkAngle.a180)
					Image.CustomPosition = new Point(x + _bounds.Width, y + _bounds.Height);
				else if (Image.Settings.WatermarkAngle == WatermarkAngle.a270)
					Image.CustomPosition = new Point(x, y + _bounds.Height);
            }
            else if (Source != null && _bounds.Contains(mousePosition))
            {
				Uri uri = new Uri("Mido;component/Styles/CursorOpenHand.cur", UriKind.RelativeOrAbsolute);
				StreamResourceInfo info = Application.GetResourceStream(uri);
                Cursor = new Cursor(info.Stream);
            }
            else
            {
                Cursor = Cursors.Arrow;
            }

            base.OnMouseMove(e);
        }
    }
}
